package com.mamingchao.designmodel.singleton_model;

/**
 * Created by mamingchao on 2020/7/21.
 */
public class SingletonModel {

    /**
     * 单例模式下的懒汉单例
     */
    public static class LazyConstruct{
        private static LazyConstruct lazyConstruct;

        public synchronized static LazyConstruct getInstance() {
            if (lazyConstruct == null) {
                lazyConstruct = new LazyConstruct();
            }
            return lazyConstruct;
        }
    }

    /**
     * 单例模式下的 饿汉单例
     *
     * 这里有个问题，就是 需要 写一个private 无参的、构造方法。
     * 这样别人用这个类的时候，就不能 new 了
     *
     * 这是最简单和实用的单例写法
     */
    static class AheadConstruct{

        private static AheadConstruct aheadConstruct = new AheadConstruct();

        public static AheadConstruct getInstance() {

            /*
                下面这个 可以注释掉，因为类加载类，类就初始化类
             */
//            if (aheadConstruct == null) {
//                aheadConstruct = new AheadConstruct();
//            }
            return aheadConstruct;
        }
    }

    /**
     * 单例模式 双重校验
     */
    static class DoubleCheck{
        private static DoubleCheck doubleCheck;

        public static DoubleCheck getInstance(){
            if (doubleCheck == null) {
                synchronized (DoubleCheck.class) {
                    if (doubleCheck == null) {
                        doubleCheck = new DoubleCheck();
                    }
                }
            }
            return doubleCheck;
        }
    }

    /**
     * 单例模式- 枚举单例
     */
    public enum  Singleton {
        INSTANCE
    }

    /**
     * 单例模式--静态内部类单例
     * 这是其中一种完美的写法
     */
    static class Singleton1 {
        private static Singleton1 singleton;

        public static Singleton1 getInstance() {
            return singletonFactory.singleton;
        }

        //TODO 这种设计，不会出现多个线程同时 getInstance,同时new出来多个对象么？
        //后续知道答案的解答：不会，jvm保证每个类加载的时候，只加载一次
        //外部类加载的时候，内部类不会加载；只有调用getInstance的时候，才会被加载
        static class singletonFactory{
            private final static Singleton1 singleton = new Singleton1();
        }
    }

}
